#include <iostream>
#include <queue>
#include <pthread.h>
#include <sys/prctl.h>
#include <assert.h>
using namespace std;

int gThreadNum = 5;

template <class T>
class ThreadPool
{
private:
    ThreadPool(int threadNum = gThreadNum)
        : threadNum_(threadNum), isStart_(false)
    {
        pthread_mutex_init(&mutex_,nullptr);
        pthread_cond_init(&cond_,nullptr);
    }
    ThreadPool(ThreadPool<T> &) = delete;
    void operator=(ThreadPool<T> &) = delete;

public:
    // 线程安全地创建单例
    static ThreadPool<T> *getInstance()
    {
        if (instance == nullptr) // 过滤掉不满足条件的
        {
            static pthread_mutex_t mutex_s = PTHREAD_MUTEX_INITIALIZER;
            pthread_mutex_lock(&mutex_s);
            if (instance == nullptr)
            {
                instance = new ThreadPool<T>();
            }
            pthread_mutex_unlock(&mutex_s);
        }
        return instance;
    }

    static void *threadRoutine(void *args)
    {
        pthread_detach(pthread_self());
        ThreadPool<T> *tp = static_cast<ThreadPool<T> *>(args);
        //prctl(PR_SET_NAME, "follower");
        while(1)
        {
            //用条件变量保证线程间的互斥和同步
            tp->lockQueue();
            while(tp->queueEmpty())
            {
                tp->waitFortask();
            }
            //从任务队列中取出任务；
            T t = tp->pop();
            tp->unlockQueue();
            t();
        }
        return nullptr;
    }
    void start()
    {
        assert(!isStart_);
        for (int i = 0; i < threadNum_; i++)
        {
            pthread_t p;
            pthread_create(&p, nullptr, threadRoutine, this); // 传入this，可以访问类内的方法
        }
        isStart_ = true;
    }

    ~ThreadPool()
    {
        pthread_mutex_destroy(&mutex_);
        pthread_cond_destroy(&cond_);
    }

    void push(const T&in)//将任务放入任务队列中
    {
        lockQueue();
        taskQueue_.push(in);
        unlockQueue();

        wakeThread();
    }
private:
    void lockQueue(){pthread_mutex_lock(&mutex_);}
    void unlockQueue(){pthread_mutex_unlock(&mutex_);}
    bool queueEmpty(){return taskQueue_.empty();}
    void waitFortask(){pthread_cond_wait(&cond_,&mutex_);}
    void wakeThread(){pthread_cond_signal(&cond_);}//依次唤醒等待队列中的线程
    T pop()//从任务队列中取出任务
    {
        T temp = taskQueue_.front();
        taskQueue_.pop();
        return temp;
    }
private:
    bool isStart_;
    int threadNum_;
    queue<T> taskQueue_;
    pthread_mutex_t mutex_;
    pthread_cond_t cond_;
    // 单例模式
    static ThreadPool<T> *instance;
};

template <class T>
ThreadPool<T> * ::ThreadPool<T>::instance = nullptr;
